package com.gree.changying.server.network.upload;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.gree.changying.utils.StringUtil;

import com.gree.changying.server.BaseAction;
import com.gree.changying.server.utils.NLog;
import com.gree.changying.server.utils.json.JsonMananger;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Create by 游德禄 on 2019-10-18
 *  用法：
 *  UploadManager uploadManager = UploadManager.getInstance(mContext);
 *         uploadManager.setOnUploadListener(new OnUploadListener() {
 *             @Override
 *             public void onProgress(int position, int percent, int bytesWritten, int totalSize) {
 *                 NLog.e("uploadManager","onProgress",position,percent,bytesWritten,totalSize);
 *                 //注意  这个getId只能在回调里面获取，是这个文件的唯一码
 *                 NLog.e("uploadManager","onProgressID",uploadManager.getId(position));
 *             }
 *
 *             @Override
 *             public void onSuccess(int position, WrapperPicUploadResponse response) {
 *                 NLog.e("uploadManager","onSuccess",position,response);
 *                 NLog.e("uploadManager","onSuccessID",uploadManager.getId(position));
 *             }
 *
 *             @Override
 *             public void onError(int position, int statusCode, String msg) {
 *                 NLog.e("uploadManager","onError",position,statusCode,msg);
 *                 NLog.e("uploadManager","onErrorID",uploadManager.getId(position));
 *             }
 *             @Override
 *             public void onFinish(int successCount, int errorCount, int allCount) {
 *                 NLog.e("uploadManager","onFinish",successCount,errorCount,allCount);
 *             }
 *         });
 *         UploadFile file = UploadFile.file("/sdf/sdfsdf/");
 *         uploadManager.addFile(file);
 *         file.setFilePath("/sdfsg/sdfsdf/sdf");
 *         uploadManager.addFile(file);
 *         uploadManager.start();
 */
public class UploadManager {
    //线程进度回调
    private final static int THREAD_PROGRESS_CODE=100;
    //线程完成
    private final static int THREAD_FINISH_CODE=101;
    //线程被中断
    private final static int THREAD_INTERRUPT_CODE=102;
    //所有线程完成
    private final static int THREAD_ALL_FINISH_CODE=103;
    //handler传递进度值
    private final static String THREAD_PERCENT="THREAD_PERCENT";
    //handler传递position值
    private final static String THREAD_POSITION="THREAD_POSITION";
    //状态码
    private final static String THREAD_STATUS_CODE="THREAD_STATUS_CODE";
    //当前大小
    private final static String THREAD_CURRENT_SIZE="THREAD_CURRENT_SIZE";
    //总大小
    private final static String THREAD_TOTAL_SIZE="THREAD_TOTAL_SIZE";
    //文本内容
    private final static String THREAD_RESPONE="THREAD_RESPONE";
    //成功数量
    private final static String THREAD_SUCCESS_COUNT="THREAD_SUCCESS_COUNT";
    //失败数量
    private final static String THREAD_ERROR_COUNT="THREAD_ERROR_COUNT";
    //所有数量
    private final static String THREAD_ALL_COUNT="THREAD_ALL_COUNT";
    //线程池核心数
    private int threadCore=3;
    //线程池
    private ExecutorService executor;
    //成功数量
    int successCount = 0;
    //失败数量
    int failedCount = 0;

    private List<UploadFile> tempFile;
    private List<UploadFile> uploadFileList;
    private OnUploadListener uploadListener;
    private UploadHandler handler;
    private Context mContext;
    private boolean isRunning = false;

    /**
     * name
     */
    private String domain =   BaseAction.DOMAIN_FLYDIY+"/anzhuang/uploadfile" ;
    /**
     * 更新文件的数组字符串 列：
     * 更新上传的文件的名称,原文件存储路径;更新文件名称…
     */
    private String updateFilePath;

    public static UploadManager getInstance(Context mContext) {
        UploadManager uploadManager = new UploadManager();
        uploadManager.mContext = mContext;
        uploadManager.isRunning = false;
        return uploadManager;
    }

    public void reset(){
        tempFile.clear();
        uploadFileList.clear();
        isRunning = false;
    }

    public UploadManager(){
        uploadFileList = new ArrayList<>();
        tempFile = new ArrayList<>();
        handler=new UploadHandler(this);
        successCount = 0;
        failedCount = 0;
    }

    /**
     * 添加上传文件
     * @param uploadFile
     */
    public UploadManager addFile(UploadFile uploadFile){
        if(!StringUtil.isEmpty(uploadFile.getFilePath())&& StringUtil.isEmpty(uploadFile.getUrl())){
            NLog.e("uploadManager","addFile", JsonMananger.beanToJsonStr(uploadFile));
            this.tempFile.add(uploadFile);
        }
        return this;
    }

    /**
     * 添加或更新
     * @param uploadFile
     * @return
     */
    public UploadManager addOrUpdateFile(UploadFile uploadFile){
        int type = uploadFile.getType();
        int position = uploadFile.getPosition();
        boolean has = false ;
        for(int i = 0 ; i < tempFile.size();i++){
            UploadFile f = tempFile.get(i);
            if(type==f.getType()&&position==f.getPosition()){
                has = true ;
                tempFile.set(i,uploadFile);
                break;
            }
        }
        if(!has){
            return addFile(uploadFile);
        }
        return this;
    }


    /**
     * 添加上传文件
     * @param uploadFile
     */
    public UploadManager addFile(List<UploadFile> uploadFile){
        this.tempFile = uploadFile;
        return this;
    }

    /**
     * 获取将要上传的文件数量
     * @return
     */
    public int getReadySize(){
        return tempFile.size();
    }

    /**
     * 清空任务
     */
    public void clear(){
        this.tempFile.clear();
        this.tempFile = new ArrayList<>();
    }


    /**
     * 设置线程数
     * @param threadCore
     * @return
     */
    public UploadManager setThreadCount(int threadCore){
        this.threadCore=threadCore;
        return this;
    }


    /**
     * 设置上传状态监听
     * @param uploadListener
     */
    public UploadManager setOnUploadListener(OnUploadListener uploadListener){
        this.uploadListener=uploadListener;
        return this;
    }


    /**
     * 中断所有线程的执行
     */
    public void shutDownNow(){
        executor.shutdownNow();
    }

    /**
     * 根据位置取得上传文件的ID
     * @param position
     * @return
     */
    public String getId(int position){
        if(position<uploadFileList.size()){
            return uploadFileList.get(position).getId();
        }
        return null;
    }

    /**
     * 取得项
     * @param position
     * @return
     */
    public UploadFile getUploadFile(int position){
        if(position<uploadFileList.size()){
            return uploadFileList.get(position);
        }
        return null;
    }

    /**
     * 根据位置获取上传的文件
     * @param type
     * @param position
     * @return
     */
    public UploadFile getUploadFile(int type, int position){
        UploadFile uploadFile = UploadFile.file("");
        uploadFile.setUrl("");
        for(int i = 0 ; i < uploadFileList.size();i++){
            UploadFile f = uploadFileList.get(i);
            if(type==f.getType()&&position==f.getPosition()){
                 uploadFile = f;
                break;
            }
        }
        return uploadFile;
    }

    /**
     * 当前用户 维修单
     * @return
     */
    public UploadManager setWxName(){
        this.domain = BaseAction.DOMAIN_FLYDIY+"/weixiu/uploadfile";
        return this;
    }

    /**
     *  当前用户 安装单
     * @return
     */
    public UploadManager setAzName(){
        //this.domain = BaseAction.DOMAIN+"/anzhuang/uploadfile";
        this.domain = BaseAction.DOMAIN_FLYDIY+"/anzhuang/uploadfile";
        return this;
    }

    /**
     * 设置更新路径
     * @param updateFilePath
     * @return
     */
    public UploadManager setUpdateFilePath(String updateFilePath){
        this.updateFilePath = updateFilePath;
        return this;
    }


    public List<UploadFile> getList(){
        return uploadFileList;
    }

    /**
     * 启动线程
     */
    public UploadManager start(){
        if(tempFile.size()==0){
            NLog.e("UploadManager","未添加上传任务");
            if(uploadListener!=null){
                uploadListener.onFinish(0,0,0);
            }
            return this;
        }
        if(isRunning){
            NLog.e("UploadManager","正在运行，暂不执行");
            if(uploadListener!=null){
                uploadListener.onFinish(0,0,0);
            }
            return this;
        }
        isRunning = true;
        uploadFileList = new ArrayList<>(tempFile);
        clear();
        executor = Executors.newFixedThreadPool(threadCore);
        int i = 0;
        final int size = uploadFileList.size();

        NLog.e("uploadManager","readyfile", JsonMananger.beanToJsonStr(uploadFileList));

        //遍历文件
        for (final UploadFile uploadBean : uploadFileList) {
            final Bundle bundle=new Bundle();
            bundle.putInt(THREAD_POSITION,i);
            i++;
            final int index = i ;
            executor.submit(new UploadProgram(mContext,domain,updateFilePath,uploadBean, new OnThreadResultListener(){
                @Override
                public void onProgressChange(final int percent,final int currentSize,final int totalSize) {
                    bundle.putInt(THREAD_PERCENT,percent);
                    bundle.putInt(THREAD_CURRENT_SIZE,currentSize);
                    bundle.putInt(THREAD_TOTAL_SIZE,totalSize);
                    Message.obtain(handler,THREAD_PROGRESS_CODE,bundle).sendToTarget();
                }

                @Override
                public void onFinish(String response) {
                    successCount++;
                    bundle.putString(THREAD_RESPONE,response);
                    Message.obtain(handler,THREAD_FINISH_CODE,bundle).sendToTarget();
                    checkRun(index,size,successCount,failedCount);
                }

                @Override
                public void onInterrupted(int statusCode, String msg) {
                    failedCount++;
                    bundle.putInt(THREAD_STATUS_CODE,statusCode);
                    bundle.putString(THREAD_RESPONE,msg);
                    Message.obtain(handler,THREAD_INTERRUPT_CODE,bundle).sendToTarget();
                    checkRun(index,size,successCount,failedCount);
                }
            }));
        }
        //关闭线程池
        executor.shutdown();
        return this;
    }

    /**
     * 检查是否执行完
     * @param index
     * @param size
     */
    protected void checkRun(int index,int size,int successCount,int failedCount){
        if(size==(failedCount+successCount)) {
            final Bundle bundle=new Bundle();
            isRunning = false ;
            clear();
            bundle.putInt(THREAD_SUCCESS_COUNT,successCount);
            bundle.putInt(THREAD_ERROR_COUNT,failedCount);
            bundle.putInt(THREAD_ALL_COUNT,size);
            this.successCount = 0;
            this.failedCount = 0;
            Message.obtain(handler,THREAD_ALL_FINISH_CODE,bundle).sendToTarget();
        }
    }

    //静态内部类+弱引用防止内存泄漏
    private static class UploadHandler extends Handler {
        private WeakReference<UploadManager> weakReference;
        private UploadHandler(UploadManager object){
            super(Looper.getMainLooper());//执行在UI线程
            weakReference=new WeakReference<>(object);
        }

        @Override
        public void handleMessage(Message msg){
            UploadManager uploadManager=weakReference.get();
            if(uploadManager!=null&&uploadManager.uploadListener!=null){
                Bundle data= (Bundle) msg.obj;
                int position;
                int percent;
                int statusCode;
                int current;
                int total;
                String text ;
                switch (msg.what){
                    case THREAD_PROGRESS_CODE:
                        position=data.getInt(THREAD_POSITION);
                        percent=data.getInt(THREAD_PERCENT);
                        current = data.getInt(THREAD_CURRENT_SIZE);
                        total = data.getInt(THREAD_TOTAL_SIZE);
                        uploadManager.uploadListener.onProgress(position,percent,current,total);
                        break;
                    case THREAD_FINISH_CODE:
                        position=data.getInt(THREAD_POSITION);
                        text = data.getString(THREAD_RESPONE);
//                        AnUploadfileRespone response = new AnUploadfileRespone();
//                        try {
//                            response = JsonMananger.jsonToBean(text,AnUploadfileRespone.class);
//                        }catch (Exception e){
//                            //如果解析不了可能服务器没正确返回json
//                            response.setStatusCode(500);
//                            response.setMessage("服务器异常，请重试!");
//                        }
                        uploadManager.uploadListener.onSuccess(position,text);
                        break;
                    case THREAD_INTERRUPT_CODE:
                        position=data.getInt(THREAD_POSITION);
                        statusCode = data.getInt(THREAD_STATUS_CODE);
                        text = data.getString(THREAD_RESPONE);
                        uploadManager.uploadListener.onError(position,statusCode,text);
                        break;
                    case THREAD_ALL_FINISH_CODE:
                        int successCount = data.getInt(THREAD_SUCCESS_COUNT);
                        int errorCount = data.getInt(THREAD_ERROR_COUNT);
                        int size = data.getInt(THREAD_ALL_COUNT);
                        uploadManager.uploadListener.onFinish(successCount,errorCount,size);
                        break;
                }
            }
        }
    }
}